package base

import (
	resp "gitee.com/lstack_light/light-utils/common/response"
	"gitee.com/lstack_light/light-utils/common/validater"
	"github.com/gin-gonic/gin"
	"k8s.io/klog"
	"net/http"
	"reflect"
)

// Binds 参数绑定
type Binds func(context *gin.Context, data interface{}) error

// Run 执行
func Run(context *gin.Context, r resp.Response) {
	if http.StatusOK != r.Code {
		context.JSON(http.StatusInternalServerError, r)
	} else {
		context.JSON(http.StatusOK, r)
	}
}

// BindParams
/**
 * 功能描述：绑定参数以及校验
 * @author KangXu
 * @param context 上下文
 * @param data 入参结构体
 * @param binds 绑定的类型
 * @return error
 */
func BindParams(context *gin.Context, data interface{}, binds ...Binds) error {
	if nil == context {
		klog.Error("gin框架的生命周期暂未开启")
		return nil
	}
	if reflect.Ptr != reflect.TypeOf(data).Kind() ||
		reflect.Struct != reflect.ValueOf(data).Type().Elem().Kind() {
		klog.Error("参数绑定异常 >>> 传入的不是结构体指针")
		return nil
	}
	if 0 < len(binds) {
		// 主动参数绑定
		for _, bind := range binds {
			err := bind(context, data)
			if nil != err {
				return err
			}
		}
	} else {
		// 按照不同请求方式实现不同的自动绑定参数
		method := context.Request.Method
		switch method {
		case http.MethodGet:
			bindings := make([]Binds, 0)
			bindings = append(bindings, BindQuery, BindUri, BindHeader)
			for _, binding := range bindings {
				err := binding(context, data)
				if nil != err {
					return err
				}
			}
		case http.MethodPost, http.MethodPut, http.MethodDelete:
			bindings := make([]Binds, 0)
			bindings = append(bindings, BindJson, BindUri, BindHeader)
			for _, binding := range bindings {
				err := binding(context, data)
				if nil != err {
					return err
				}
			}
		}
	}
	// 参数校验
	err := validater.DefaultValidate(data)
	if nil != err {
		return err
	}
	context = nil
	return nil
}

// BindJson 绑定body参数
func BindJson(ctx *gin.Context, data interface{}) error {
	return ctx.ShouldBindJSON(data)
}

// BindQuery 绑定query参数
func BindQuery(ctx *gin.Context, data interface{}) error {
	return ctx.ShouldBindQuery(data)
}

// BindUri 绑定uri参数
func BindUri(ctx *gin.Context, data interface{}) error {
	return ctx.ShouldBindUri(data)
}

// BindHeader 绑定header参数
func BindHeader(ctx *gin.Context, data interface{}) error {
	return ctx.ShouldBindHeader(data)
}
